﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SearchOperations
{
    //public class Search
    //{
    //    private static ProbaTravelDataContext cont;

    //    static Search()
    //    {
    //        cont = new ProbaTravelDataContext();
    //    }

    //    private static List<TravelVariant> GetVariants(List<ComplexDestination> searchedList, int maxChanges)
    //    {
    //        List<TravelVariant> result = new List<TravelVariant>();

    //        foreach (ComplexDestination compl in searchedList)
    //        {
    //            List<long> dest = GetAllDestination(compl.settlementID.First());
    //            List<long> nextDest = GetAllDestination(compl.settlementID.ElementAt(1));
    //            List<long> intersectLast = dest.Intersect(nextDest).ToList();
    //            List<long> intersectNew = Clone(intersectLast);

    //            int counterLast = 1;
    //            TravelVariant travel = new TravelVariant();
    //            travel.SettlementID.Add(compl.settlementID.First());

    //            while (counterLast < compl.settlementID.Count)
    //            {
    //                while (intersectNew.Count > 0)
    //                {
    //                    counterLast++;
    //                    intersectLast = Clone(intersectNew);
    //                    if (counterLast == compl.settlementID.Count) { break; }
    //                    nextDest = GetAllDestination(compl.settlementID.ElementAt(counterLast));
    //                    intersectNew = intersectLast.Intersect(nextDest).ToList();
    //                }
    //                counterLast--;
    //                if (counterLast == compl.settlementID.Count - 1)
    //                {
    //                    travel.SettlementID.Add(compl.settlementID.ElementAt(counterLast));
    //                    break;
    //                }
    //                travel.SettlementID.Add(compl.settlementID.ElementAt(counterLast));
    //                dest = GetAllDestination(compl.settlementID.ElementAt(counterLast));
    //                nextDest = GetAllDestination(compl.settlementID.ElementAt(counterLast + 1));
    //                intersectLast = dest.Intersect(nextDest).ToList();
    //                intersectNew = Clone(intersectLast);
    //                counterLast++;
    //            }
    //            result.Add(travel);
    //        }

    //        List<TravelVariant> listToRemove = new List<TravelVariant>();

    //        foreach (TravelVariant tr in result)
    //        {
    //            if (tr.SettlementID.Count - 2 > maxChanges)
    //            {
    //                listToRemove.Add(tr);
    //            }
    //        }

    //        foreach (TravelVariant tr in listToRemove)
    //        {
    //            result.Remove(tr);
    //        }

    //        return result;
    //    }

    //    private static List<ComplexDestination> GetFullList(long startPoint, long endPoint)
    //    {
    //        List<ComplexDestination> complexDestList = new List<ComplexDestination>();
    //        List<ComplexDestination> searchedList = new List<ComplexDestination>();
    //        List<ComplexDestination> listToRemove = new List<ComplexDestination>();
    //        List<ComplexDestination> listToAdd = new List<ComplexDestination>();
    //        ComplexDestination compl = new ComplexDestination();
    //        compl.settlementID.Add(startPoint);
    //        complexDestList.Add(compl);

    //        while (complexDestList.Count > 0)
    //        {
    //            foreach (ComplexDestination complexDestination in complexDestList)
    //            {
    //                if (complexDestination.settlementID.Last() == endPoint)
    //                {
    //                    searchedList.Add(complexDestination);
    //                    listToRemove.Add(complexDestination);
    //                }
    //                else
    //                {
    //                    List<long> allNextSettlementsID =
    //                        GetAllNextSettlementsID(complexDestination.settlementID.Last());

    //                    foreach (long settlementID in allNextSettlementsID)
    //                    {
    //                        if (!complexDestination.settlementID.Contains(settlementID))
    //                        {
    //                            ComplexDestination complex = new ComplexDestination();
    //                            complex.settlementID = Clone(complexDestination.settlementID);
    //                            complex.settlementID.Add(settlementID);
    //                            listToAdd.Add(complex);
    //                        }
    //                    }

    //                    listToRemove.Add(complexDestination);
    //                }
    //            }

    //            foreach (ComplexDestination complAdd in listToAdd)
    //            {
    //                complexDestList.Add(complAdd);
    //            }

    //            foreach (ComplexDestination complRem in listToRemove)
    //            {
    //                complexDestList.Remove(complRem);
    //            }

    //            listToRemove.Clear();
    //            listToAdd.Clear();
    //        }

    //        return searchedList;
    //    }

    //    private static List<long> Clone(List<long> list)
    //    {
    //        List<long> newList = new List<long>();

    //        foreach (long l in list)
    //        {
    //            newList.Add(l);
    //        }

    //        return newList;
    //    }

    //    //dij-1
    //    public static List<long> GetAllNextSettlementsID(long settlementID)
    //    {
    //        List<long> destinationListID = GetAllDestination(settlementID);
    //        List<long> allNextSettlementsID = new List<long>();

    //        foreach (long destinationID in destinationListID)
    //        {
    //            long nextSettlementID = GetNextSettlementID(destinationID, settlementID);

    //            if (nextSettlementID != -1)
    //            {
    //                allNextSettlementsID.Add(nextSettlementID);
    //            }
    //        }

    //        return allNextSettlementsID;
    //    }

    //    //dij-2(1)
    //    private static long GetNextSettlementID(long destinstionID, long settlementID)
    //    {
    //        int currentOrderNumber = GetCurrentOrderNumber(destinstionID, settlementID);

    //        var orderNumberList = from d in cont.Destinations
    //                              join w in cont.WayStations
    //                              on d.DestinationID equals w.DestinationID
    //                              where d.DestinationID == destinstionID & w.WayStationOrderNumber > currentOrderNumber
    //                              orderby w.WayStationOrderNumber
    //                              select w.SettlementID;

    //        if (orderNumberList.ToList().Count > 0)
    //        {
    //            return orderNumberList.ToList().First();
    //        }
    //        else
    //        {
    //            return -1;
    //        }
    //    }

    //    //dij(2)
    //    private static int GetCurrentOrderNumber(long destinstionID, long settlementID)
    //    {
    //        var currentNumber = (from d in cont.Destinations
    //                             join w in cont.WayStations
    //                             on d.DestinationID equals w.DestinationID
    //                             where d.DestinationID == destinstionID & w.SettlementID == settlementID
    //                             select w.WayStationOrderNumber).First();

    //        return currentNumber;
    //    }

    //    //dij(1)
    //    public static List<long> GetAllDestination(long settlementID)
    //    {
    //        var destinationListID = from d in cont.Destinations
    //                                join w in cont.WayStations
    //                                on d.DestinationID equals w.DestinationID
    //                                where w.SettlementID == settlementID
    //                                select d.DestinationID;

    //        return destinationListID.ToList();
    //    }

    //    public static List<WayStation> GetAllWayStationForSettlement(long settlementID)
    //    {
    //        var allWay = from w in cont.WayStations
    //                     where w.SettlementID == settlementID
    //                     select w;

    //        return allWay.ToList();
    //    }

    //    private static long GetWayStationID(long destinationID, long settlementID)
    //    {
    //        var wayStationID = (from d in cont.Destinations
    //                            join w in cont.WayStations
    //                            on d.DestinationID equals w.DestinationID
    //                            where d.DestinationID == destinationID & w.SettlementID == settlementID
    //                            select w.WayStationID).First();

    //        return wayStationID;
    //    }

    //    //dij
    //    public static List<RoadSegment> GetRoadSegments(long settlementStartID, long settlementEndID)
    //    {
    //        List<RoadSegment> roadSegmentList = new List<RoadSegment>();

    //        var destStart = from d in cont.Destinations
    //                        join w in cont.WayStations
    //                        on d.DestinationID equals w.DestinationID
    //                        where w.SettlementID == settlementStartID
    //                        select w.DestinationID;

    //        var destEnd = from d in cont.Destinations
    //                      join w in cont.WayStations
    //                      on d.DestinationID equals w.DestinationID
    //                      where w.SettlementID == settlementEndID
    //                      select w.DestinationID;

    //        foreach (long l in destStart.ToList().Intersect(destEnd).ToList())
    //        {
    //            RoadSegment roadSegment = new RoadSegment();
    //            roadSegment.StartWayStationID = GetWayStationID(l, settlementStartID);
    //            roadSegment.EndWayStationID = GetWayStationID(l, settlementEndID);
    //            roadSegmentList.Add(roadSegment);
    //        }
    //        return roadSegmentList;
    //    }

    //    public static List<Route> GetAllRoutes(DateTime date, long startID, long endID, int maxChanges)
    //    {
    //        List<Route> routeList = new List<Route>();
    //        List<ComplexDestination> searchedList = GetFullList(startID, endID);
    //        List<TravelVariant> variantList = GetVariants(searchedList, maxChanges);

    //        if (variantList.Count == 0)
    //        {
    //            return routeList;
    //        }

    //        foreach (TravelVariant tVariant in variantList)
    //        {
    //            List<RoadSegment> rsList = GetRoadSegments(tVariant.SettlementID.ElementAt(0),
    //                tVariant.SettlementID.ElementAt(1));

    //            foreach (RoadSegment rSegment in rsList)
    //            {
    //                List<DateTime> startHours = GetStartHours(rSegment, date);

    //                foreach (DateTime startHour in startHours)
    //                {
    //                    TimedRoadSegment trSegment = new TimedRoadSegment(rSegment, startHour);
    //                    Route route = new Route();

    //                    SegmentInfo sInfo = new SegmentInfo();
    //                    decimal price;

    //                    sInfo.DestinationName = string.Format("Destination: " + GetDestinationName(rSegment.StartWayStationID));
    //                    sInfo.StartHour = startHour;
    //                    sInfo.RoadSegments = GetSegmentNames(rSegment);
    //                    sInfo.EndHour = startHour.AddMinutes(GetTimeForRoadSegment(rSegment.StartWayStationID,
    //                        rSegment.EndWayStationID, false)); ;
    //                    route.DisplayInfo.Add(sInfo);
    //                    price = GetPriceForRoadSegment(rSegment);
    //                    route.Price = price;

    //                    StringBuilder wayStationInfo = new StringBuilder();
    //                    wayStationInfo.Append(startHour + "," + rSegment.StartWayStationID + "," + rSegment.EndWayStationID + ";");

    //                    for (int i = 1; i < tVariant.SettlementID.Count - 1; i++)
    //                    {
    //                        TimedRoadSegment nextSegment = GetNextTimedRoadSegment(trSegment, tVariant.SettlementID.ElementAt(i),
    //                            tVariant.SettlementID.ElementAt(i + 1));
    //                        SegmentInfo sNextInfo = new SegmentInfo();

    //                        sNextInfo.DestinationName = string.Format("Destination: " +
    //                            GetDestinationName(nextSegment.RoadSegment.StartWayStationID));
    //                        sNextInfo.StartHour = nextSegment.StartHour;
    //                        sNextInfo.RoadSegments = GetSegmentNames(nextSegment.RoadSegment);
    //                        sNextInfo.EndHour = nextSegment.StartHour.AddMinutes(GetTimeForRoadSegment
    //                            (nextSegment.RoadSegment.StartWayStationID, nextSegment.RoadSegment.EndWayStationID, false));

    //                        route.DisplayInfo.Add(sNextInfo);
    //                        route.Price += GetPriceForRoadSegment(nextSegment.RoadSegment);
    //                        wayStationInfo.Append(nextSegment.StartHour + "," + nextSegment.RoadSegment.StartWayStationID + "," +
    //                            nextSegment.RoadSegment.EndWayStationID + ";");

    //                        trSegment = nextSegment;
    //                    }

    //                    TimeSpan ts = route.DisplayInfo.Last().EndHour - route.DisplayInfo.First().StartHour;

    //                    string hours = (ts.Days * 24 + ts.Hours).ToString();
    //                    string minutes = ts.Minutes.ToString();

    //                    if (minutes.Equals("0") == true)
    //                    {
    //                        minutes = "00";
    //                    }
    //                    route.TotalTime = string.Format("{0},{1}", hours, minutes);

    //                    route.WayStationInfo = wayStationInfo.ToString();

    //                    routeList.Add(route);
    //                }
    //            }
    //        }

    //        SortRouteList(ref routeList);
    //        int pointer = -1;
    //        decimal minPrice = routeList.First().Price;

    //        for (int i = 1; i < routeList.Count; i++)
    //        {
    //            if (routeList.ElementAt(i).Price > ((decimal)3 * minPrice))
    //            {
    //                pointer = i;
    //                break;
    //            }
    //        }

    //        if (pointer != -1)
    //        {
    //            routeList.RemoveRange(pointer, routeList.Count - pointer);
    //        }

    //        return routeList;
    //    }

    //    public static decimal GetPriceForRoadSegment(RoadSegment rSegment)
    //    {
    //        int startNumber = GetCurrentOrderNumber(rSegment.StartWayStationID);
    //        int endNumber = GetCurrentOrderNumber(rSegment.EndWayStationID);
    //        long destinationID = GetDestinationIDForWayStation(rSegment.EndWayStationID);

    //        var price = (from d in cont.Destinations
    //                     join w in cont.WayStations
    //                     on d.DestinationID equals w.DestinationID
    //                     where w.WayStationOrderNumber > startNumber & w.WayStationOrderNumber <= endNumber
    //                     & w.DestinationID == destinationID
    //                     select w.WayStationPriceTo).Sum();

    //        return price;
    //    }

    //    private static string GetSegmentNames(RoadSegment rSegment)
    //    {
    //        StringBuilder wayStationNames = new StringBuilder();

    //        int startNumber = GetCurrentOrderNumber(rSegment.StartWayStationID);
    //        int endNumber = GetCurrentOrderNumber(rSegment.EndWayStationID);
    //        long destinationId = GetDestinationIDForWayStation(rSegment.EndWayStationID);

    //        var names = from d in cont.Destinations
    //                    join w in cont.WayStations
    //                    on d.DestinationID equals w.DestinationID
    //                    join s in cont.Settlements
    //                    on w.SettlementID equals s.SettlementID
    //                    where w.WayStationOrderNumber >= startNumber & w.WayStationOrderNumber <= endNumber
    //                    & w.DestinationID == destinationId
    //                    orderby w.WayStationOrderNumber
    //                    select s.SettlementName;

    //        foreach (string str in names.ToList())
    //        {
    //            wayStationNames.Append(str);
    //            wayStationNames.Append('-');
    //        }

    //        wayStationNames.Remove(wayStationNames.Length - 1, 1);

    //        return wayStationNames.ToString();
    //    }

    //    public static int GetCurrentOrderNumber(long wayStationID)
    //    {
    //        int orderNumber = (from w in cont.WayStations
    //                           where w.WayStationID == wayStationID
    //                           select w.WayStationOrderNumber).First();

    //        return orderNumber;
    //    }

    //    private static string GetDestinationName(long wayStationID)
    //    {
    //        string destinationName = (from d in cont.Destinations
    //                                  join w in cont.WayStations
    //                                  on d.DestinationID equals w.DestinationID
    //                                  where w.WayStationID == wayStationID
    //                                  select d.DestistionName).First();

    //        return destinationName;
    //    }

    //    private static TimedRoadSegment GetNextTimedRoadSegment(TimedRoadSegment trSegment, long startSettlementID,
    //        long endSettlementID)
    //    {
    //        List<RoadSegment> rsList = GetRoadSegments(startSettlementID, endSettlementID);
    //        List<DateTime> startHours = new List<DateTime>();
    //        DateTime temp;
    //        DateTime min;
    //        RoadSegment searchedSegment = new RoadSegment();

    //        int timeForRoadSegment = GetTimeForRoadSegment(trSegment.RoadSegment.StartWayStationID,
    //            trSegment.RoadSegment.EndWayStationID, false);

    //        DateTime arriveHour = trSegment.StartHour.AddMinutes(timeForRoadSegment);

    //        temp = arriveHour;
    //        min = arriveHour.AddDays(8);

    //        foreach (RoadSegment rs in rsList)
    //        {
    //            while (startHours.Count == 0)
    //            {
    //                foreach (DateTime d in GetStartHours(rs, temp))
    //                {
    //                    if (d > arriveHour)
    //                    {
    //                        startHours.Add(d);
    //                        break;
    //                    }
    //                }
    //                temp = temp.AddDays(1);
    //            }

    //            foreach (DateTime d in startHours)
    //            {
    //                if (d < min)
    //                {
    //                    min = d;
    //                    searchedSegment = rs;
    //                }
    //            }
    //            startHours.Clear();
    //            temp = arriveHour;
    //        }

    //        return new TimedRoadSegment(searchedSegment, min);
    //    }

    //    //Dij
    //    public static DateTime GetNextStartHour(DateTime arriveHour, long startSettlementID,
    //        long endSettlementID)
    //    {
    //        List<RoadSegment> rsList = GetRoadSegments(startSettlementID, endSettlementID);
    //        List<DateTime> startHours = new List<DateTime>();
    //        DateTime temp;
    //        DateTime min;

    //        temp = arriveHour;
    //        min = arriveHour.AddDays(8);

    //        foreach (RoadSegment rs in rsList)
    //        {
    //            while (startHours.Count == 0)
    //            {
    //                foreach (DateTime d in GetStartHours(rs, temp))
    //                {
    //                    if (d > arriveHour)
    //                    {
    //                        startHours.Add(d);
    //                        break;
    //                    }
    //                }
    //                temp = temp.AddDays(1);
    //            }

    //            foreach (DateTime d in startHours)
    //            {
    //                if (d < min)
    //                {
    //                    min = d;
    //                }
    //            }
    //            startHours.Clear();
    //            temp = arriveHour;
    //        }

    //        return min;
    //    }

    //    private static long GetDestinationIDForWayStation(long wayStationID)
    //    {
    //        var destinationID = (from d in cont.Destinations
    //                             join w in cont.WayStations
    //                             on d.DestinationID equals w.DestinationID
    //                             where w.WayStationID == wayStationID
    //                             select d.DestinationID).First();

    //        return destinationID;
    //    }

    //    public static List<DateTime> GetStartHours(RoadSegment rSegment, DateTime date)
    //    {
    //        List<DateTime> result = new List<DateTime>();
    //        long currentDestinationID = GetDestinationIDForWayStation(rSegment.StartWayStationID);

    //        var firstWayStationID = (from w in cont.WayStations
    //                                 where w.DestinationID == currentDestinationID
    //                                 & w.WayStationOrderNumber == 1
    //                                 select w.WayStationID).First();

    //        int time = GetTimeForRoadSegment(firstWayStationID, rSegment.StartWayStationID, true);

    //        int dayOfWeekIDPrevious = (int)date.AddDays(-1).DayOfWeek;

    //        var startHoursPrevious = from d in cont.Destinations
    //                                 join s in cont.StartHours
    //                                 on d.DestinationID equals s.DestinationID
    //                                 where s.SheduleTypeID == dayOfWeekIDPrevious & s.StartHourValue >= (1440 - time)
    //                                 & d.DestinationID == currentDestinationID
    //                                 orderby s.StartHourValue
    //                                 select s.StartHourValue;

    //        foreach (int i in startHoursPrevious)
    //        {
    //            DateTime d = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0).AddMinutes(i + time);
    //            result.Add(d);
    //        }

    //        int dayOfWeekIDPresent = (int)date.DayOfWeek;

    //        var startHoursPresent = from d in cont.Destinations
    //                                join s in cont.StartHours
    //                                on d.DestinationID equals s.DestinationID
    //                                where s.SheduleTypeID == dayOfWeekIDPresent & s.StartHourValue <= (1440 - time)
    //                                & d.DestinationID == currentDestinationID
    //                                orderby s.StartHourValue
    //                                select s.StartHourValue;

    //        foreach (int i in startHoursPresent)
    //        {
    //            DateTime d = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0).AddMinutes(i + time);
    //            result.Add(d);
    //        }

    //        return result;
    //    }

    //    private static int GetTimeForRoadSegment(long startWayStationID,
    //        long endWayStationID, bool lastStayInclude)
    //    {
    //        int result;
    //        if (startWayStationID == endWayStationID)
    //        {
    //            result = 0;
    //        }
    //        else
    //        {
    //            long destinationID = (from w in cont.WayStations
    //                                  where w.WayStationID == startWayStationID
    //                                  select w.DestinationID).First();

    //            int startOrderNumber = (from w in cont.WayStations
    //                                    where w.WayStationID == startWayStationID
    //                                    select w.WayStationOrderNumber).First();

    //            int endOrderNumber = (from w in cont.WayStations
    //                                  where w.WayStationID == endWayStationID
    //                                  select w.WayStationOrderNumber).First();

    //            var timeTravelList = from w in cont.WayStations
    //                                 where w.DestinationID == destinationID & w.WayStationOrderNumber > startOrderNumber
    //                                 & w.WayStationOrderNumber <= endOrderNumber
    //                                 select w.WayStationTimeTo;

    //            int timeTravel;

    //            timeTravel = (from w in cont.WayStations
    //                          where w.DestinationID == destinationID & w.WayStationOrderNumber > startOrderNumber
    //                          & w.WayStationOrderNumber <= endOrderNumber
    //                          select w.WayStationTimeTo).Sum();

    //            int timeStay;

    //            if (lastStayInclude)
    //            {
    //                var timeStayList = from w in cont.WayStations
    //                                   where w.DestinationID == destinationID & w.WayStationOrderNumber > startOrderNumber
    //                                   & w.WayStationOrderNumber <= endOrderNumber
    //                                   select w.WayStationStay;

    //                timeStay = (from w in cont.WayStations
    //                            where w.DestinationID == destinationID & w.WayStationOrderNumber > startOrderNumber
    //                            & w.WayStationOrderNumber <= endOrderNumber
    //                            select w.WayStationStay).Sum();
    //            }
    //            else
    //            {
    //                var timeStayList = from w in cont.WayStations
    //                                   where w.DestinationID == destinationID & w.WayStationOrderNumber > startOrderNumber
    //                                   & w.WayStationOrderNumber < endOrderNumber
    //                                   select w.WayStationStay;

    //                if (timeStayList.ToList().Count == 0)
    //                {
    //                    timeStay = 0;
    //                }
    //                else
    //                {
    //                    timeStay = (from w in cont.WayStations
    //                                where w.DestinationID == destinationID & w.WayStationOrderNumber > startOrderNumber
    //                                & w.WayStationOrderNumber < endOrderNumber
    //                                select w.WayStationStay).Sum();
    //                }
    //            }
    //            result = timeStay + timeTravel;
    //        }

    //        return result;
    //    }

    //    private static void SortRouteList(ref  List<Route> list)
    //    {
    //        for (int i = 0; i < list.Count - 1; i++)
    //        {
    //            if (list.ElementAt(i).CompareTo(list.ElementAt(i + 1)) > 0)
    //            {
    //                list.Reverse(i, 2);
    //            }
    //        }
    //    }

    //    //dij
    //    public static List<long> GetAllSettlementID()
    //    {
    //        var allSettlements = from s in cont.Settlements
    //                             select s.SettlementID;

    //        return allSettlements.ToList();
    //    }

    //    //dij-Unfinished
    //    //public static decimal GetPriceSettlements(long startID, long endID)
    //    //{
    //    //    List<long> commonDest = DijkstraSearching.GetCommonDest(startID, endID);

    //    //    decimal price = (from w in cont.WayStations
    //    //                     join s in cont.Settlements
    //    //                     on w.SettlementID equals s.SettlementID
    //    //                     where w.DestinationID == commonDest.First() &
    //    //                     w.SettlementID == endID
    //    //                     select w.WayStationPriceTo).First();

    //    //    return price;
    //    //}

    //    //dij
    //    public static ComplexDestination CloneComplex(ComplexDestination compl)
    //    {
    //        ComplexDestination cloned = new ComplexDestination();

    //        foreach (long l in compl.settlementID)
    //        {
    //            cloned.settlementID.Add(l);
    //        }

    //        return cloned;
    //    }

    //    //public static TimeSpan GetTimeSettlement(long startSettID, long endSettID)
    //    //{
    //    //    long destID = DijkstraSearching.GetCommonDest(startSettID, endSettID).First();

    //    //    long startWay = (from w in cont.WayStations
    //    //                     where w.SettlementID == startSettID &
    //    //                     w.DestinationID == destID
    //    //                     select w.WayStationID).First();

    //    //    long endWay = (from w in cont.WayStations
    //    //                   where w.SettlementID == endSettID &
    //    //                   w.DestinationID == destID
    //    //                   select w.WayStationID).First();

    //    //    int minutes = GetTimeForRoadSegment(startWay, endWay, false);

    //    //    TimeSpan result = new TimeSpan(0, minutes, 0);

    //    //    return result;
    //    //}

    //}
}
